/**
 * @author 0283000115
 * @date 2017年11月30日-上午10:27:27
 */
package com.zte.claa.inficombo.csa.app.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author 0283000115
 *
 */

public class HttpClientUtils {
	private static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
			
	// utf-8字符编码
    public static final String CHARSET_UTF_8 = "utf-8";

    // HTTP内容类型。
    public static final String CONTENT_TYPE_TEXT_HTML = "text/xml";

    // HTTP内容类型。相当于form表单的形式，提交数据
    public static final String CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";

    // HTTP内容类型。相当于form表单的形式，提交数据
    public static final String CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";
    
    // 默认user-agent.
    public static final String HEADER_USER_AGENT = "Mozilla/5.0 Chrome/50.0.2661.102 Safari/537.36";
    
    // 连接管理器
    private static PoolingHttpClientConnectionManager PoolConnManager;

    // 请求配置
    private static RequestConfig requestConfig;
    
    // 请求重试处理 
    private static HttpRequestRetryHandler httpRequestRetryHandler;
    
    // keepalive策略.
    private static ConnectionKeepAliveStrategy keepAliveStrategy;
    
    // httpclient连接池检查线程池.
    private static ScheduledExecutorService connPoolCheckSvr;

    // 初始化httpclient连接池和公共配置.
    static {
    	initCommonParas();
    	startHttpclientPoolChecker();
    }
    
    /**
     * 公共参数初始化.
     */
	private static void initCommonParas() {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				public boolean isTrusted(X509Certificate[] chain, String authType) {
					return true;
				}
			}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

			// 1.设置连接池，同时支持http和https
			ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
			Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
					.register("http", plainsf)
					.register("https", sslsf)
					.build();
			PoolConnManager = new PoolingHttpClientConnectionManager(registry);
			// 将最大连接数增加
			PoolConnManager.setMaxTotal(100);
			// 将每个路由基础的连接增加
			PoolConnManager.setDefaultMaxPerRoute(50);

			// 2.请求重试处理
			httpRequestRetryHandler = new HttpRequestRetryHandler() {
				@Override
				public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
					// 如果已经重试了3次，就放弃
					if (executionCount >= 3) {
						return false;
					}
					// 如果服务器丢掉了连接，那么就重试
					if (exception instanceof NoHttpResponseException) {
						return true;
					}
					// 不要重试SSL握手异常
					if (exception instanceof SSLHandshakeException) {
						return false;
					}
					// 超时
					if (exception instanceof InterruptedIOException) {
						return false;
					}
					// 目标服务器不可达
					if (exception instanceof UnknownHostException) {
						return false;
					}
					// 连接被拒绝
					if (exception instanceof ConnectTimeoutException) {
						return false;
					}
					// SSL握手异常
					if (exception instanceof SSLException) {
						return false;
					}
					HttpClientContext clientContext = HttpClientContext.adapt(context);
					HttpRequest request = clientContext.getRequest();
					// 如果请求是幂等的，就再次尝试
					if (!(request instanceof HttpEntityEnclosingRequest)) {
						return true;
					}
					return false;
				}
			};

			// 3.配置请求的超时设置
			requestConfig = RequestConfig.custom()
					// 一、连接目标服务器超时时间：ConnectionTimeout-->指的是连接一个url的连接等待时间
					.setConnectTimeout(15000)
					// 二、读取目标服务器数据超时时间：SocketTimeout-->指的是连接上一个url，获取response的返回等待时间
					.setSocketTimeout(20000)
					// 三、从连接池获取连接的超时时间:ConnectionRequestTimeout
					.setConnectionRequestTimeout(10000)
					.setCookieSpec(CookieSpecs.STANDARD)
					.build();

			// 4.keepalive策略
			keepAliveStrategy = new DefaultConnectionKeepAliveStrategy() {
				@Override
				public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
					long keepAlive = super.getKeepAliveDuration(response, context);
					if (keepAlive == -1) {
						// 如果服务器没有设置keep-alive这个参数，我们就把它设置成3分钟
						keepAlive = 3 * 60000L;
					}
					return keepAlive;
				}
			};
			logger.info("[**]HttpClientUtils初始化完成!");
		} catch (Exception e) {
			logger.error("[**]HttpClientUtils初始化异常！", e);
		}
	}
	
	// 启动连接池检查线程.
	private static void startHttpclientPoolChecker(){
		connPoolCheckSvr = Executors.newScheduledThreadPool(1);
		Runnable r = new Runnable() {
			@Override
			public void run() {
				// 关闭过期的连接（超过keepalive设置的期限.
				PoolConnManager.closeExpiredConnections();  
				// 关闭空闲时间超过60秒的连接  
				PoolConnManager.closeIdleConnections(3*60, TimeUnit.SECONDS);  
			}
		};
		// 延迟10秒钟启动，每10秒钟检查一次.
		connPoolCheckSvr.scheduleWithFixedDelay(r, 10, 10, TimeUnit.SECONDS);
		logger.info("[**]httpclient pool connPoolCheckSvr start!");
	}
    
    /**
     * 获取httpclient
     * 
     * @return
     */
    public static CloseableHttpClient getHttpClient() { 
    	
    	return HttpClients.custom()
    			.setConnectionManager(PoolConnManager)
    			.setDefaultRequestConfig(requestConfig)
    			.setKeepAliveStrategy(keepAliveStrategy)
    			.setRetryHandler(httpRequestRetryHandler)
    			.setUserAgent(HEADER_USER_AGENT)
    			.build();   
    }

    /**
     * 发送Post请求 (http)
     * 
     * @param httpPost
     * @return
     */
    private static String sendHttpPost(HttpPost httpPost, CloseableHttpClient httpClnt) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String responseContent = null;
        InputStream in = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = (httpClnt == null) ? getHttpClient() : httpClnt;
            // 执行请求
            response = httpClient.execute(httpPost);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            // in.close();作用就是将用完的连接释放，下次请求可以复用，这里特别注意的是，
            // 如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭，并且不能被复用，这样就失去了采用连接池的意义。
            in = entity.getContent();
            
            // 可以获得响应头
            // Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
            // for (Header header : headers) {
            // System.out.println(header.getName());
            // }
            
            // 得到响应类型
            // ContentType.getOrDefault(response.getEntity()).getMimeType();
            // 判断响应状态
            
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception("HTTP Request is failed and response code is " + response.getStatusLine().getStatusCode());
            }
            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }
        } finally {
        	try{
        		if(in != null){
        			in.close();
        			in = null;
        		}
        	}catch(Exception ignore){} 
        	try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
        return responseContent;
    }

    /**
     * 发送Get请求 
     * 
     * @param httpGet
     * @return
     */
    private static String sendHttpGet(HttpGet httpGet, CloseableHttpClient httpClnt) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String responseContent = null;
        InputStream in = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = (httpClnt == null) ? getHttpClient() : httpClnt;
            // 执行请求
            response = httpClient.execute(httpGet);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            // in.close();作用就是将用完的连接释放，下次请求可以复用，这里特别注意的是，
            // 如果不使用in.close();而仅仅使用response.close();结果就是连接会被关闭，并且不能被复用，这样就失去了采用连接池的意义。
            in = entity.getContent();
            
            // 可以获得响应头
            // Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
            // for (Header header : headers) {            
            //    System.out.println(header.getName());
            // }

            // 得到响应类型
            // System.out.println(ContentType.getOrDefault(response.getEntity()).getMimeType());

            // 判断响应状态
            if (response.getStatusLine().getStatusCode() >= 300) {
                throw new Exception("HTTP Request is failed and response code is " + response.getStatusLine().getStatusCode());
            }
            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                responseContent = EntityUtils.toString(entity, CHARSET_UTF_8);
                EntityUtils.consume(entity);
            }
        } finally {
        	try{
        		if(in != null){
        			in.close();
        			in = null;
        		}
        	}catch(Exception ignore){}
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
        return responseContent;
    }
    
    /**
     * 发送 post请求 (http)
     * 
     * @param httpUrl
     *            地址
     * @param httpClnt 为空时内部自动从httclient池中获取httclient.
     */
    public static String sendHttpPost(String httpUrl, CloseableHttpClient httpClnt) throws Exception {
        // 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 get请求 (http)
     * 
     * @param httpUrl
     */
    public static String sendHttpGet(String httpUrl, CloseableHttpClient httpClnt) throws Exception {
        // 创建get请求
        HttpGet httpGet = new HttpGet(httpUrl);
        return HttpClientUtils.sendHttpGet(httpGet, httpClnt);
    }

    /**
     * 发送 post请求（带文件） (http)
     * 
     * @param httpUrl
     *            地址
     * @param maps
     *            参数
     * @param fileLists
     *            附件
     */
    public static String sendHttpPost(String httpUrl, Map<String, String> maps, List<File> fileLists, CloseableHttpClient httpClnt)  throws Exception {
        HttpPost httpPost = new HttpPost(httpUrl);
        MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
        if (maps != null) {
            for (String key : maps.keySet()) {
                meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
            }
        }
        if (fileLists != null) {
            for (File file : fileLists) {
                FileBody fileBody = new FileBody(file);
                meBuilder.addPart("files", fileBody);
            }
        }
        HttpEntity reqEntity = meBuilder.build();
        httpPost.setEntity(reqEntity);
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 post请求 (http)
     * 
     * @param httpUrl
     *            地址
     * @param params
     *            参数(格式:key1=value1&key2=value2)
     * 
     */
    public static String sendHttpPost(String httpUrl, String params, CloseableHttpClient httpClnt)  throws Exception {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        // 设置参数
        if (params != null && params.trim().length() > 0) {
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType(CONTENT_TYPE_FORM_URL);
            httpPost.setEntity(stringEntity);
        }
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 post请求 (http)
     * 
     * @param maps 参数
     */
    public static String sendHttpPost(String httpUrl, Map<String, String> maps, CloseableHttpClient httpClnt)  throws Exception {
        String parem = HttpClientUtils.convertStringParamter(maps);
        return HttpClientUtils.sendHttpPost(httpUrl, parem, httpClnt);
    }   
    
    /**
     * 发送 post请求 发送json数据 (http)
     * 
     * @param httpUrl 地址
     * @param paramsJson 参数(格式 json)
     * 
     */
    public static String sendHttpPostJson(String httpUrl, String paramsJson, CloseableHttpClient httpClnt)  throws Exception {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        httpPost.setHeader("Content-Type", CONTENT_TYPE_JSON_URL);
        httpPost.setHeader("Accept", "application/json");  
        // 设置参数
        if (paramsJson != null && paramsJson.trim().length() > 0) {
            StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");
            stringEntity.setContentType(CONTENT_TYPE_JSON_URL);
            stringEntity.setContentEncoding(CHARSET_UTF_8);
            httpPost.setEntity(stringEntity);
        }
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }
    
    /**
     * 发送 post请求 发送json数据 (http)
     * 
     * @param httpUrl 地址
     * @param paramsJson 参数(格式 json)
     * 
     *  setHeader(name, value)：如果Header中没有定义则添加，如果已定义则用新的value覆盖原用value值。
     *  addHeader(name, value)：如果Header中没有定义则添加，如果已定义则保持原有value不改变。
     * 
     */
    public static String sendHttpPostJsonWithHeadPara(String httpUrl, String paramsJson, Map<String, String> headParaMap, CloseableHttpClient httpClnt)  throws Exception {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        // 设置http的header参数.
        httpPost.setHeader("Content-Type", CONTENT_TYPE_JSON_URL);
        httpPost.setHeader("Accept", "application/json");  
        if(headParaMap != null){
        	Iterator<String> hpIt = headParaMap.keySet().iterator();
        	while(hpIt.hasNext()){
        		String pn = hpIt.next();
        		String pv = headParaMap.get(pn);
        		httpPost.setHeader(pn, pv);
        	}
        }
        // 设置Body部分的JSON参数
        if (paramsJson != null && paramsJson.trim().length() > 0) {
            StringEntity stringEntity = new StringEntity(paramsJson, "UTF-8");
            stringEntity.setContentType(CONTENT_TYPE_JSON_URL);
            stringEntity.setContentEncoding(CHARSET_UTF_8);
            httpPost.setEntity(stringEntity);
        }
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }
    
    /**
     * 发送 post请求 发送json数据 (http)
     * 
     * @param httpUrl 地址
     * @param paramsJson 参数(格式 json)
     * 
     */
    public static String sendHttpPostByFormURL(String httpUrl, Map<String, String> psm, CloseableHttpClient httpClnt)  throws Exception {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        httpPost.setHeader("Content-Type", CONTENT_TYPE_FORM_URL);
        httpPost.setHeader("Accept", "application/json");          
        List<NameValuePair> nvps = new ArrayList<NameValuePair>();  
        if(psm != null){  
            for (Entry<String, String> entry : psm.entrySet()) {  
                nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));  
            }  
        }  
        //设置参数到请求对象中  
        httpPost.setEntity(new UrlEncodedFormEntity(nvps, CHARSET_UTF_8));   
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }
    
    /**
     * 发送 post请求 发送xml数据 (http)
     * 
     * @param httpUrl   地址
     * @param paramsXml  参数(格式 Xml)
     * 
     */
    public static String sendHttpPostXml(String httpUrl, String paramsXml, CloseableHttpClient httpClnt) throws Exception {
        HttpPost httpPost = new HttpPost(httpUrl);
        // 设置参数
        if (paramsXml != null && paramsXml.trim().length() > 0) {
            StringEntity stringEntity = new StringEntity(paramsXml, "UTF-8");
            stringEntity.setContentType(CONTENT_TYPE_TEXT_HTML);
            stringEntity.setContentEncoding(CHARSET_UTF_8);
            httpPost.setEntity(stringEntity);
        }
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }
    
    /**
     * http/https发送 post请求 （basicAuthKey模式）
     * 
     * @param httpUrl 地址
     */
    public static String sendHttpPostWithBasicAuth(String httpUrl, String basicAuthKey, CloseableHttpClient httpClnt) throws Exception {
        // 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        // 注意：Basic和basicAuthKey之间有个空格.
        httpPost.addHeader("Authorization", "Basic " + basicAuthKey); 
        return HttpClientUtils.sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 get请求
     * 
     * @param httpUrl
     */
    public static String sendHttpsGetWithBasicAuth(String httpUrl, String basicAuthKey, CloseableHttpClient httpClnt) throws Exception {
        // 创建get请求
        HttpGet httpGet = new HttpGet(httpUrl);
        // 注意：Basic和basicAuthKey之间有个空格.
        httpGet.addHeader("Authorization", "Basic " + basicAuthKey); 
        return HttpClientUtils.sendHttpGet(httpGet, httpClnt);
    }

    /**
     * 发送 post请求（带文件）
     * 
     * @param httpUrl
     *            地址
     * @param maps
     *            参数
     * @param fileLists
     *            附件
     */
    public static String sendHttpPostWithBasicAuth(String httpUrl, Map<String, String> maps, List<File> fileLists, String basicAuthKey, CloseableHttpClient httpClnt)  throws Exception {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        // 注意：Basic和basicAuthKey之间有个空格.
        httpPost.addHeader("Authorization", "Basic " + basicAuthKey); 
        MultipartEntityBuilder meBuilder = MultipartEntityBuilder.create();
        if (maps != null) {
            for (String key : maps.keySet()) {
                meBuilder.addPart(key, new StringBody(maps.get(key), ContentType.TEXT_PLAIN));
            }
        }
        if (fileLists != null) {
            for (File file : fileLists) {
                FileBody fileBody = new FileBody(file);
                meBuilder.addPart("files", fileBody);
            }
        }
        HttpEntity reqEntity = meBuilder.build();
        httpPost.setEntity(reqEntity);
        return sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 post请求
     * 
     * @param httpUrl
     *            地址
     * @param params
     *            参数(格式:key1=value1&key2=value2)
     * 
     */
    public static String sendHttpPostWithBasicAuth(String httpUrl, String params, String basicAuthKey, CloseableHttpClient httpClnt)  throws Exception  {
    	// 创建httpPost
        HttpPost httpPost = new HttpPost(httpUrl);
        // 注意：Basic和basicAuthKey之间有个空格.
        httpPost.addHeader("Authorization", "Basic " + basicAuthKey); 
        try {
            // 设置参数
            if (params != null && params.trim().length() > 0) {
                StringEntity stringEntity = new StringEntity(params, "UTF-8");
                stringEntity.setContentType(CONTENT_TYPE_FORM_URL);
                httpPost.setEntity(stringEntity);
            }
        } catch (Exception e) {
            logger.error("sendHttpPost failde with format: "+CONTENT_TYPE_FORM_URL, e);
            throw e;
        }
        return sendHttpPost(httpPost, httpClnt);
    }

    /**
     * 发送 post请求
     * 
     * @param maps
     *            参数
     */
    public static String sendHttpPostWithBasicAuth(String httpUrl, Map<String, String> maps, String basicAuthKey, CloseableHttpClient httpClnt) throws Exception {
        String parem = convertStringParamter(maps);
        return sendHttpPostWithBasicAuth(httpUrl, parem, basicAuthKey, httpClnt);
    }    

    /**
     * 将map集合的键值对转化成：key1=value1&key2=value2 的形式
     * 
     * @param parameterMap
     *            需要转化的键值对集合
     * @return 字符串
     */
    public static String convertStringParamter(Map<String, String> parameterMap) {
        StringBuffer parameterBuffer = new StringBuffer();
        if (parameterMap != null) {
            Iterator<String> iterator = parameterMap.keySet().iterator();
            String key = null;
            String value = null;
            while (iterator.hasNext()) {
                key = iterator.next();
                if (parameterMap.get(key) != null) {
                    value = parameterMap.get(key);
                } else {
                    value = "";
                }
                parameterBuffer.append(key).append("=").append(value);
                if (iterator.hasNext()) {
                    parameterBuffer.append("&");
                }
            }
        }
        return parameterBuffer.toString();
    }
    
    /**
     * 解析json字符串
     * 
     * @param jsonStr
     * @return
     */
    public static JSONObject parseJsonStr(String jsonStr) throws Exception {
    	 return new JSONObject(jsonStr);
    }
    
    // test!
    public static void main2(String[] args) throws Exception {        
        // 'http://api.map.baidu.com/geoconv/v1/?coords='+corrds+'&from=1&to=5&ak=8NkwmuRWaBcFbHZB5iNHPZpd&callback=?'
        // String url = "http://api.map.baidu.com/geoconv/v1/?coords=114.123456,29.123432;114.123456,29.123432&from=1&to=5&ak=8NkwmuRWaBcFbHZB5iNHPZpd";
        String url = "http://183.230.96.66:8087/v2/gprsusedinfosingle";
        String rsp = HttpClientUtils.sendHttpPost(url, null);
        System.out.println(rsp);
        JSONObject json = HttpClientUtils.parseJsonStr(rsp);
        System.out.println(json.get("status")+", message="+json.get("message").toString());
        JSONArray orgRetArr = json.getJSONArray("result");
        System.out.println("size="+orgRetArr.length());
    }
}
